import { _decorator, Animation, AudioClip, clamp, Component, Event, EventTouch, Node, PhysicsSystem2D, ScrollView, Tween, tween, UIOpacity, UITransform, v2, v3, Vec2, Vec3, view } from 'cc';
import { ChangeManager } from './ChangeManager';
import { Person } from './Person';
import { Panel, UIManager } from '../../Scripts/Framework/Managers/UIManager';
import { GameData } from './GameData';
import { Character } from './Character';
import { PoolManager } from '../../Scripts/Framework/Managers/PoolManager';
import { ProjectEvent, ProjectEventManager } from '../../Scripts/Framework/Managers/ProjectEventManager';
const { ccclass, property } = _decorator;

@ccclass('MigaManager')
export class MigaManager extends Component {

    private static instance: MigaManager;
    public static get Instance(): MigaManager {
        return this.instance;
    }

    @property(Node)
    game: Node;

    @property(Node)
    express: Node;

    @property(Node)
    closeExpress: Node;

    @property(Node)
    charecterPanel: Node;

    @property(Node)
    change: Node;

    @property(Node)
    closeChara: Node;

    @property(Node)
    content: Node;

    @property(Node)
    tutorial: Node;

    @property(Node)
    hand: Node;

    @property(ScrollView)
    scrollView: ScrollView;

    @property([AudioClip])
    clips: AudioClip[] = [];

    lastPos: Vec2;
    touchPanel: Node;

    edgePoint: EventTouch;

    chooseCharacter: Character;
    touchPerson: Person;
    lastPerson: Person;
    allPersons: Person[] = [];

    protected onLoad(): void {
        MigaManager.instance = this;
        // PhysicsSystem2D.instance.debugDrawFlags = 1;
        ProjectEventManager.emit(ProjectEvent.游戏开始);
    }

    start() {
        this.InitTutorial();
        this.InitGame();
        this.InitCharacter();
    }

    update(deltaTime: number) {
        if (this.edgePoint) this.GameMove(this.edgePoint);
    }

    InitTutorial() {
        this.tutorial.active = GameData.Instance.getNumberData("Tutorial") == 0;
        if (GameData.tutorial == 5) {
            this.tutorial.children[0].children[0].active = false;
            this.tutorial.children[0].children[5].active = true;
            this.hand.setPosition(this.tutorial.children[0].children[GameData.tutorial].getPosition());
        }
    }

    NextTutorial() {
        if (GameData.tutorial == this.tutorial.children[0].children.length - 1) {
            GameData.Instance.setNumberData("Tutorial", 1);
            this.tutorial.active = false;
            return;
        }
        this.tutorial.children[0].children[GameData.tutorial].active = false;
        GameData.tutorial++;
        this.tutorial.children[0].children[GameData.tutorial].active = true;
        if (GameData.tutorial == 1) this.hand.getComponent(Animation).play("handCharacter");
        else if (GameData.tutorial == 8) this.hand.getComponent(Animation).play("handItem");
        else if (GameData.tutorial == 9) this.hand.active = false;
        else {
            this.hand.getComponent(Animation).play();
            this.hand.setPosition(this.tutorial.children[0].children[GameData.tutorial].getPosition());
        }
    }

    InitGame() {
        let game: Node = PoolManager.GetNodeByPrefab(GameData.prefabsBundle.get("Games/" + GameData.gameName), this.game);
        game.setPosition(v3(570, 0));
        this.touchPanel = game.children[game.children.length - 1];
        game.on(Node.EventType.TOUCH_START, this.GameTouchStart, this);
        game.on(Node.EventType.TOUCH_MOVE, this.GameTouchMove, this);
        let persons = game.getComponentsInChildren(Person);
        this.allPersons.push(...(persons));
        for (let i = 0; i < this.allPersons.length; i++) {
            const element = this.allPersons[i];
            if (element.defaultId != undefined && element.defaultId != null && element.defaultId != -1) {
                let data = GameData.Instance.getRecordData("PersonData");
                element.DataInit(data[element.defaultId]);
            }
        }
        this.schedule(this.CheckIndex, 0.1);
    }

    InitCharacter() {
        let data = GameData.Instance.getRecordData("PersonData");
        for (let i = 0; i < data.length; i++) {
            const element = data[i];
            let bool = false;
            for (let j = 0; j < this.allPersons.length; j++) {
                const element2 = this.allPersons[j];
                if (element2.id == element.id) {
                    bool = true;
                    break;
                }
            }
            let chara = Character.Init(this.content);
            chara.Init(element);
            chara.node.setScale(v3(0.55, 0.55, 0.55));
            if (bool) chara.node.active = false;
        }
        this.content.on(Node.EventType.TOUCH_START, this.CharacterTouchStart, this);
        this.content.on(Node.EventType.TOUCH_MOVE, this.CharacterTouchMove, this);
        this.content.on(Node.EventType.TOUCH_END, this.CharacterTouchEnd, this);
        this.content.on(Node.EventType.TOUCH_CANCEL, this.CharacterTouchEnd, this);
    }

    CheckIndex() {
        let game = this.game.children[0];
        let arrY: (Node | number)[][] = [];
        let specLayers: Node[][] = [];
        for (let i = 0; i < game.children.length; i++) {
            const element = game.children[i];
            arrY.push([element, element.getPosition().y]);
            if ((element.getComponent("Item") as any)?.otherplane) {
                if (specLayers.length == 0) specLayers.push([(element.getComponent("Item") as any).otherplane.node, element]);
                else {
                    let bool = false;
                    for (let i = 0; i < specLayers.length; i++) {
                        const element2 = specLayers[i][0];
                        if (element2 == (element.getComponent("Item") as any).otherplane.node) {
                            bool = true;
                            specLayers[i].push(element);
                        }
                    }
                    if (!bool) specLayers.push([(element.getComponent("Item") as any).otherplane.node, element]);
                }
            }
        }
        arrY.sort((a, b) => { return b[1] as number - (a[1] as number) });
        for (let i = 0; i < arrY.length; i++) {
            const element = arrY[i][0] as Node;
            element.setSiblingIndex(i);
        }
        for (let i = 0; i < this.allPersons.length; i++) {
            const element = this.allPersons[i];
            if (element.layerFloor) element.node.setSiblingIndex(element.layerFloor.layer.getSiblingIndex() - 1);
        }
        for (let i = 0; i < specLayers.length; i++) {
            const element = specLayers[i];
            let arr: (Node | number)[][] = [];
            for (let j = 1; j < element.length; j++) {
                const element2: Node = element[j];
                arr.push([element2, element2.getPosition().y]);
            }
            arr.sort((a, b) => { return b[1] as number - (a[1] as number) });
            for (let j = 0; j < arr.length; j++) {
                const element2 = arr[j][0] as Node;
                element2.setSiblingIndex(element[0].getSiblingIndex() + j - 1);
            }
        }
        this.touchPanel.setSiblingIndex(game.children.length - 1);
    }

    Back() {
        if (this.tutorial.active) return;
        this.unscheduleAllCallbacks();
        PoolManager.PutNode(this.game.children[0]);
        UIManager.ShowPanel(Panel.LoadingPanel, "WorldScene");
    }

    ChangeCharacter() {
        if (this.tutorial.active) {
            if (GameData.tutorial == 2) this.NextTutorial();
            else return;
        }
        this.unscheduleAllCallbacks();
        PoolManager.PutNode(this.game.children[0]);
        ChangeManager.GoChangeScene();
    }

    Express() {
        if (this.tutorial.active) {
            if (GameData.tutorial == 6) this.NextTutorial();
            else return;
        }
        this.closeExpress.active = !this.closeExpress.active;
        Tween.stopAllByTarget(this.express);
        tween(this.express)
            .to(0.5, { position: v3(!this.closeExpress.active ? 1637 : 85, 0) })
            .start();
    }

    PlayExpress(event: Event) {
        if (!this.lastPerson) return UIManager.ShowTip("请先和人物互动！");
        let target: Node = event.target;
        let num = target.getSiblingIndex();
        if (this.tutorial.active) {
            if (GameData.tutorial == 7 && num == 1) this.NextTutorial();
            else return;
        }
        this.lastPerson.Express(num);
    }

    OpenCharacterPanel() {
        if (this.tutorial.active) {
            if (GameData.tutorial != 0) return;
            else this.NextTutorial();
        }
        this.closeChara.active = !this.closeChara.active;
        if (this.closeChara.active) this.change.active = true;
        Tween.stopAllByTag(0);
        tween(this.change.getComponent(UIOpacity)).tag(0)
            .to(0.5, { opacity: this.closeChara.active ? 255 : 0 })
            .call(() => {
                if (!this.closeChara.active) this.change.active = false;
            })
            .start();
        tween(this.charecterPanel).tag(0)
            .by(0.5, { position: v3(this.closeChara.active ? 361 : -361, 0) })
            .start();
    }

    GameTouchStart(event: EventTouch) {
        if (this.tutorial.active) return;
        this.lastPos = event.getUILocation();
    }

    GameTouchMove(event: EventTouch) {
        if (this.tutorial.active) return;
        let target: Node = event.target;
        if (!target.name.includes("Game")) return;
        let deltaX = event.getUILocation().subtract(this.lastPos).x;
        let pos = target.getPosition().add3f(deltaX, 0, 0);
        let uitr = target.getComponent(UITransform);
        let limit = (uitr.width - view.getVisibleSize().width) / 2;
        pos.x = clamp(pos.x, -limit, limit);
        target.setPosition(pos);
        this.lastPos = event.getUILocation();
    }

    GameMove(event: EventTouch) {
        if (this.tutorial.active) return;
        let x = event.getUILocation().x;
        let mul = 0;
        if (x < 100) mul = 1;
        else if (x > view.getVisibleSize().width - 100) mul = -1;
        if (mul == 0) return;
        let moveX = mul;
        let game = this.game.children[0];
        let pos = game.getPosition();
        pos.x += moveX * 30;
        let uitr = game.getComponent(UITransform);
        let limit = (uitr.width - view.getVisibleSize().width) / 2;
        pos.x = clamp(pos.x, -limit, limit);
        let deltaX = pos.x - game.getPosition().x;
        let target: Node = event.target;
        let targetPos = target.getPosition();
        targetPos.x -= deltaX;
        target.setPosition(targetPos);
        game.setPosition(pos);
    }

    CharacterTouchStart(event: EventTouch) {
        if (this.tutorial.active) {
            this.scrollView.enabled = false;
            if (GameData.tutorial != 1) return;
        }
        let pos = event.getUILocation();
        let pos2 = this.content.getComponent(UITransform).convertToNodeSpaceAR(v3(pos.x, pos.y));
        pos = v2(pos2.x, pos2.y);
        for (let i = 0; i < this.content.children.length; i++) {
            const element = this.content.children[i];
            if (element.active && element.getComponent(UITransform).getBoundingBox().contains(pos)) {
                if (this.tutorial.active && i == 0 || !this.tutorial.active) this.chooseCharacter = element.getComponent(Character);
                break;
            }
        }
    }

    CharacterTouchMove(event: EventTouch) {
        if (this.tutorial.active && GameData.tutorial != 1) return;
        let pos = event.getUILocation();
        if (!this.chooseCharacter) return;
        if (!this.touchPerson) {
            if (this.content.getComponent(UITransform).getBoundingBoxToWorld().contains(pos)) return;
            this.touchPerson = Person.Init(this.touchPanel);
            this.touchPerson.node.setWorldPosition(v3(pos.x, pos.y));
            this.allPersons.push(this.touchPerson);
            let data = GameData.Instance.getRecordData("PersonData");
            this.touchPerson.DataInit(data[this.chooseCharacter.id]);
            this.touchPerson.TouchStart(event);
            this.scrollView.enabled = false;
            this.content.children.find((value, index, obj) => { if (value.getComponent(Character).id == this.chooseCharacter.id) return value }).active = false;
        }
        else if (this.touchPerson) this.touchPerson.TouchMove(event);
    }

    CharacterTouchEnd(event: EventTouch) {
        if (this.tutorial.active && GameData.tutorial != 1) return;
        this.chooseCharacter = null;
        if (this.touchPerson) {
            this.touchPerson.TouchEnd(event);
            this.touchPerson = null;
        }
        this.scrollView.enabled = true;
    }

    RecyclePerson(id: number) {
        let chara = this.content.children.find((value, index, obj) => { if (value.getComponent(Character).id == id) return value; });
        chara.active = true;
    }

}